package saves.objects;

import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.World;
import saves.Area;
import saves.EntidadeNave;

/**
 *
 * @author u11173
 */
public class Projetil extends Corpo {
    private static final long serialVersionUID = 1L;
    
    public static int[][] TYPES = {
        //   0          1         2            3               4            5        6              7         8
        //onTimeOut, timeOut, onContact, default pDamage, default eDamage, image, ini_speed*100, selectable, mass (g)
        {1, 10000, 1, 1, 0,   9,  10,  0, 100}, //Bullet
        {0, 0,     2, 2, 1,   10, 10,  0, 1}, //Missile
        {2, 7500,  0, 0, 4,   12, 0,   1, 10000}, //Bomb
        {2, 7500,  0, 0, -10, 11, 0,   1, 10000} //A-Bomb
    };
    
    public static float[] ENERGY_COSTS = new float[] { .1f, 5, 5, 10 };
    public static boolean[] HAS_COOLDOWN = new boolean[] { false, true, true, true };    
    public static int COOLDOWN = 500; //in ms
    
    protected Projetil() {}
        
    /**
     * Determines what happens with this projectile when timed out.
     * 0 Means nothing (does not have a time out)
     * 1 Means it is destroyed
     * 2 Means it explodes
     */    
    private int onTimeOut;
    
    /**
     * The time after its creation (in ms) in which this projectile will excute it's onTimeOut action.
     */
    private int timeOut;
    
    /**
     * Determines what happens with this projectile upon contact.
     * -1 They do not collide (static and ethereal)
     * 0 Means nothing
     * 1 Means it is destroyed
     * 2 Means it explodes
     */
    private int onContact;
    
    /**
     * The damage caused by this projectile upon contact.
     * If it is 0, it means it does not cause damage by contact.
     */
    private float projectileDamage;
    
    /**
     * The damage caused by this projectile's explosion.
     * If 0, it means that this projectile never explodes.
     * If negative, means implosion.
     */
    private float explosionDamage;
    
    /**
     * Determines wether this object is selectable.
     */
    private boolean selectable;
    
    /**
     * The owner of this projectile, if any. It is used for XP attribution.
     */
    private EntidadeNave owner;
    
    public Projetil(float x, float y, float ang, int type, float potency, EntidadeNave owner, World world) {
        super(x, y, ang, TYPES[type][5], TYPES[type][2] == -1 || TYPES[type][8] == 0 ? BodyType.KINEMATIC : BodyType.DYNAMIC, world);
        
        this.onTimeOut = TYPES[type][0];
        this.timeOut = TYPES[type][1];
        this.onContact = TYPES[type][2];
        this.projectileDamage = potency * TYPES[type][3];
        this.explosionDamage = potency * TYPES[type][4];
        this.selectable = TYPES[type][7] == 1;
        
        this.owner = owner;
        this.body.m_mass = (float) TYPES[type][8]/1000;
        
        float speed = (float) TYPES[type][6]/100;
        this.body.setLinearVelocity(new Vec2((float) (speed*Math.cos(ang)), (float) (speed*Math.sin(ang))));
    }
    
    @Override
    public boolean isSelectable() {
        return selectable;
    }
    
    @Override
    public void update(int delta, Area a) {
        super.update(delta, a);
        if (onTimeOut != 0 && timeOut > 0) {
            timeOut -= delta;
            if (timeOut <= 0) {
                if (onTimeOut == 2)
                    explode(a);
                this.setDestruir();
            }
        }
    }
    
    public void explode(Area a) {
        if (explosionDamage > 0)
            a.addExplosion(this.body.getPosition(), explosionDamage/10, owner); //explode everything!
        else if (explosionDamage < 0)
            a.addImplosion(this.body.getPosition(), explosionDamage/10, owner); //explode everything!        
    }
    
    @Override
    protected void onCollide(Area a, Corpo c) {
        if (c != null && projectileDamage != 0)
            c.harm(projectileDamage/10, EntidadeNave.DamageType.PROJECTILE, owner);
        
        if (onContact == 1) //only destroy
            this.setDestruir();
        else if (onContact == 2) {
            explode(a);
            this.setDestruir();
        }
    }
}
